﻿using System;
using System.Collections.Generic;
using System.Text;

namespace SsLib
{
    public abstract class SimSet : SimObject
    {
        public class Linkage : SimObject
        {
            internal Linkage SUC;
            internal Linkage PRED;

            public Link Suc()
            {
                return this.SUC as Link;
            }

            public Link Pred()
            {
                return this.PRED as Link;
            }

            public Linkage Prev()
            {
                return this.PRED;
            }
        }

        public class Link : Linkage
        {
            public void Out()
            {
                if (this.SUC != null)
                {
                    this.SUC.PRED = this.PRED;
                    this.PRED.SUC = this.SUC;
                    this.SUC = null;
                    this.PRED = null;
                }
            }

            public void Follow(Linkage ptr)
            {
                Out();
                if (ptr != null && ptr.SUC != null)
                {
                    this.PRED = ptr;
                    this.SUC = ptr.SUC;

                    ptr.SUC = this;
                    this.SUC.PRED = this;
                }
            }

            public void Precede(Linkage ptr)
            {
                Out();
                if (ptr != null && ptr.SUC != null)
                {
                    this.SUC = ptr;
                    this.PRED = ptr.PRED;
                    ptr.PRED = this;
                    this.PRED.SUC = this;
                }
            }

            public void Into(Head S)
            {
                Precede(S);
            }
        }

        public class Head : Linkage
        {
            public Link First()
            {
                return this.Suc();
            }

            public Link Last()
            {
                return this.Pred();
            }

            public bool Empty()
            {
                return (this.SUC == this);
            }

            public int Cardinal()
            {
                int i = 0;
                Link ptr = this.First();

                while (ptr != null)
                {
                    i++;
                    ptr = ptr.Suc();
                }
                return i;
            }

            public void Clear()
            {
                while (this.First() != null) this.First().Out();
            }

            public Head()
                : base()
            {
                this.SUC = this;
                this.PRED = this;
            }
        }
    }
}
